const int inf = 1e9;
void solve()
{
  int n, m;
  cin >> n >> m;

  if (n < m) {
    swap(n, m);
  }

  vvvi dp(n + 1, vvi(1 << m, vi(1 << m, inf)));
  int t = (1 << m) - 1;
  rep(i, 0, t) {
    dp[1][i][0] = 0;
    rep(j, 0, m - 1) {
      if (i >> j & 1) {
        dp[1][i][0]++;
      }
    }
  }

  auto f = [&](int v) {
    return (int)(__builtin_popcount(v));
  };

  int ans = inf;
  rep(i, 2, n) {
    rep(j1, 0, t) {
      rep(j2, 0, t) {
        if (dp[i - 1][j2][j1] == inf) {
          continue;
        }
        rep(j3, 0, t) {
          bool ok = true;
          rep(j, 0, m - 1) {
            int d1 = j1 >> j & 1;
            int d2 = j2 >> j & 1;
            int d3 = j3 >> j & 1;
            
            if (!d3 && !d2) {
              if (!d1 && !((j > 0 && (j2 >> (j - 1) & 1)) || (j < m - 1 && (j2 >> (j + 1) & 1)))) {
                ok = false;
                break;
              }
            }
          }
          if (!ok) {
            continue;
          }
          int tmp = f(j3);
          dp[i][j3][j2] = min(dp[i][j3][j2], dp[i - 1][j2][j1] + tmp);
          if (i == n) {
            rep(j, 0, m - 1) {
              int d1 = j1 >> j & 1;
              int d2 = j2 >> j & 1;
              int d3 = j3 >> j & 1;
              
              if (!d3 && !d2) {
                if (!d1 && !((j > 0 && (j2 >> (j - 1) & 1)) || (j < m - 1 && (j2 >> (j + 1) & 1)))) {
                  ok = false;
                  break;
                }
                if (!((j > 0 && (j3 >> (j - 1) & 1)) || (j < m - 1 && (j3 >> (j + 1) & 1)))) {
                  ok = false;
                  break;
                }
              }
            }
            if (ok) {
              ans = min(ans, dp[i - 1][j2][j1] + tmp);
            }
          }
        }
      }
    }
  }

  if (m == 1) {
    ans = (n + 2) / 3;
  }
  cout << n * m - ans;
}